/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package dataanalysis.gui.dataviewer;

import java.util.HashSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;
import weka.core.Attribute;
import weka.core.Instances;
import weka.filters.Filter;
import weka.filters.unsupervised.attribute.NominalToString;
import weka.filters.unsupervised.attribute.StringToNominal;

/**
 *
 * @author Administrator
 */
public class VariableTableModel implements TableModel {

    private HashSet m_Listeners;
    private Instances m_Data;
    private int m_minRows;
    private int m_numAttributes;
    private int m_numCols;
    private int m_numRows;
    private boolean[] m_isSelected;

    public VariableTableModel(int r) {
        m_Listeners = new HashSet();
        m_minRows = r;
        m_numAttributes = 0;
        m_numRows = r;
        m_numCols = 8;
        m_Data = null;
        m_isSelected = null;
    }

    public void setInstances(Instances data) {
        if(data==null) return;
        if (data.classIndex() == -1) {
            data.setClassIndex(data.numAttributes() - 1);
        }
        m_Data = data;
        m_numAttributes = m_Data.numAttributes();
        m_numRows = m_minRows > m_numAttributes ? m_minRows : m_numAttributes;
        m_isSelected = new boolean[m_numAttributes];
        for (int i = 0; i < m_numAttributes; i++) {
            m_isSelected[i] = true;
        }
    }

    public int getRowCount() {
        return m_numRows;
    }

    public int getColumnCount() {
        return m_numCols;
    }

    public String getColumnName(int columnIndex) {
        if (columnIndex < 0 || columnIndex >= m_numCols) {
            return null;
        }
        switch (columnIndex) {
            case 0:
                return "变量名称";
            case 1:
                return "变量类型";
            case 2:
                return "是否选中";
            case 3:
                return "是否类别";
            case 4:
                return "变量均值";
            case 5:
                return "变量熵";
            case 6:
                return "变量方差";
            case 7:
                return "变量标准差";
            default:
                return null;
        }
    }

    public Class<?> getColumnClass(int columnIndex) {
        if (columnIndex < 0 || columnIndex >= m_numCols) {
            return null;
        }
        switch (columnIndex) {
            case 0:
                return String.class;
            case 1:
                return String.class;
            case 2:
                return Boolean.class;
            case 3:
                return Boolean.class;
            case 4:
                return Object.class;
            case 5:
            case 6:
            case 7:
                return Double.class;
            default:
                return null;
        }
    }

    public boolean isCellEditable(int rowIndex, int columnIndex) {
        if (rowIndex < 0 || rowIndex > m_numAttributes || columnIndex > 3) {
            return false;
        } else {
            return true;
        }
    }

    public Object getValueAt(int rowIndex, int columnIndex) {
        if (columnIndex < 0 || columnIndex >= m_numCols || rowIndex < 0 || rowIndex >= m_numAttributes) {
            return null;
        }
        switch (columnIndex) {
            case 0:
                return m_Data.attribute(rowIndex).name();
            case 1:
                return getTypeString(m_Data.attribute(rowIndex).type());
            case 2:
                return m_isSelected[rowIndex];
            case 3:
                return m_Data.classIndex() == rowIndex;
            case 4:
                return m_Data.meanOrMode(rowIndex);
            case 5:
                return null;
            case 6:
                if (m_Data.attribute(rowIndex).type() != Attribute.NUMERIC) {
                    return null;
                }
                return m_Data.variance(rowIndex);
            case 7:
                if (m_Data.attribute(rowIndex).type() != Attribute.NUMERIC) {
                    return null;
                }
                return Math.sqrt(m_Data.variance(rowIndex));
            default:
                return null;
        }
    }

    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
        //允许在表格末行的下一行添加新变量
        if (columnIndex < 0 || columnIndex >= m_numCols || rowIndex < 0 || rowIndex > m_numAttributes) {
            return;
        }
        if (rowIndex == m_numAttributes) {
            return;
        }
        Instances copy = new Instances(m_Data);
        if (columnIndex == 0) {
            if (rowIndex == m_numAttributes) {
                return;
            }
            m_Data.renameAttribute(rowIndex, aValue.toString());
        } else if (columnIndex == 1) {
            if (rowIndex == m_numAttributes) {
                return;
            }
            String type = getTypeString(m_Data.attribute(rowIndex).type());
            String index = String.valueOf(rowIndex + 1);
            if (type.equals("STRING")) {
                if (aValue.toString().equals("NOMINAL")) {
                    try {
                        StringToNominal filter = new StringToNominal();
                        filter.setAttributeIndex(index);
                        filter.setInputFormat(copy);
                        m_Data = Filter.useFilter(copy, filter);
                    } catch (Exception ex) {
                        Logger.getLogger(VariableTableModel.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            } else if (type.equals("NOMINAL")) {
                if (aValue.toString().equals("STRING")) {
                    try {
                        NominalToString filter = new NominalToString();
                        filter.setAttributeIndexes(index);
                        filter.setInputFormat(copy);
                        m_Data = Filter.useFilter(copy, filter);
                    } catch (Exception ex) {
                        Logger.getLogger(VariableTableModel.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
        } else if (columnIndex == 2) {
            if (rowIndex == m_numAttributes) {
                return;
            }
            m_isSelected[rowIndex] = (Boolean) aValue;
        } else if (columnIndex == 3) {
            if (rowIndex == m_numAttributes) {
                return;
            }
            m_Data.setClassIndex(rowIndex);
        }
    }

    public void addTableModelListener(TableModelListener l) {
        m_Listeners.add(l);
    }

    public void removeTableModelListener(TableModelListener l) {
        m_Listeners.remove(l);
    }

    private String getTypeString(int type) {
        switch (type) {
            case Attribute.DATE:
                return "DATE";
            case Attribute.NOMINAL:
                return "NOMINAL";
            case Attribute.NUMERIC:
                return "NUMERIC";
            case Attribute.RELATIONAL:
                return "RELATIONAL";
            case Attribute.STRING:
                return "STRING";
            default:
                return null;
        }
    }
}
